package com.rp.article.controller;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.util.StrUtil;
import com.mongodb.client.gridfs.GridFSBucket;
import com.rp.article.config.RabbitMQConfig;
import com.rp.article.serivce.ArticleService;
import com.rp.bo.NewArticleBO;
import com.rp.news.common.*;
import com.rp.news.enums.ArticleCoverType;
import com.rp.news.enums.ArticleReviewStatus;
import com.rp.news.enums.YesOrNo;
import com.rp.news.exception.GraceException;
import com.rp.news.util.RedisOperator;
import com.rp.pojo.Category;
import com.rp.vo.ArticleDetailVO;
import freemarker.template.Configuration;
import freemarker.template.Template;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpStatus;
import org.bson.types.ObjectId;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.validation.Valid;
import java.io.File;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.Writer;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@Slf4j
@Api(value = "文章业务controller", tags = {"文章业务controller"})
@RequestMapping("article")
public class ArticleController {


    @Autowired
    private ArticleService articleService;

    @Autowired
    private GridFSBucket gridFSBucket;


    @Value("${freemarker.html.target}")
    private String htmlTarget;


    @Autowired
    public RedisOperator redis;


    @Autowired
    public RestTemplate restTemplate;


    @PostMapping("/createArticle")
    @ApiOperation(value = "用户发文", notes = "用户发文", httpMethod = "POST")
    public Result createArticle(@RequestBody @Valid NewArticleBO newArticleBO) {

        //判断文章封面类型, 单图必填 纯文字则设置为空
        if (newArticleBO.getArticleType() == ArticleCoverType.ONE_IMAGE.type) {
            if (StrUtil.isBlank(newArticleBO.getArticleCover())) {
                return Result.errorCustom(ResponseStatusEnum.ARTICLE_COVER_NOT_EXIST_ERROR);
            }
        } else {
            newArticleBO.setArticleCover("");
        }
        Category tmpt = null;
        String catStr = redis.get(RedisCommon.REDIS_ALL_CATEGORY);
        if (StrUtil.isBlank(catStr)) {
            return Result.errorCustom(ResponseStatusEnum.SYSTEM_OPERATION_ERROR);
        } else {
            List<Category> convert = Convert.convert(new TypeReference<List<Category>>() {
            }, catStr);

            for (Category c : convert) {
                if (c.getId() == newArticleBO.getCategoryId()) {
                    tmpt = c;
                    break;

                }
            }

            if (tmpt == null) {
                return Result.errorCustom(ResponseStatusEnum.ARTICLE_CATEGORY_NOT_EXIST_ERROR);
            }
        }

        articleService.createArticle(newArticleBO, tmpt);

        return Result.ok();
    }

    @PostMapping("/queryMyList")
    @ApiOperation(value = "查询用户的所有文章列表", notes = "查询用户的所有文章列表", httpMethod = "POST")
    public Result queryMyList(String userId, String keyword, Integer status, Date startDate, Date endDate, Integer page, Integer pageSize) {

        if (StrUtil.isBlank(userId)) {
            return Result.errorCustom(ResponseStatusEnum.ARTICLE_QUERY_PARAMS_ERROR);
        }

        if (page == null) {
            page = NewsCommon.COMMON_START_PAGE;
        }

        if (pageSize == null) {
            pageSize = NewsCommon.COMMON_PAGE_SIZE;
        }

        PagedResult result = articleService.queryMyList(userId,
                keyword, status, startDate, endDate, page, pageSize);


        return Result.ok(result);
    }

    @PostMapping("/queryAllList")
    @ApiOperation(value = "管理员查询用户的所有文章列表", notes = "管理员查询用户的所有文章列表", httpMethod = "POST")
    public Result queryAllList(Integer status, Integer page, Integer pageSize) {
        PagedResult pagedResult = articleService.queryAllList(status, page, pageSize);
        return Result.ok(page);
    }

    @PostMapping("/doReview")
    @ApiOperation(value = "管理员对文章审核通过或者审核失败", notes = "管理员对文章审核通过或者审核失败", httpMethod = "POST")
    public Result doReview(String articleId, Integer passOrNot) {
        Integer pendingStatus;
        if (passOrNot == YesOrNo.YES.type) {
            //审核成功
            pendingStatus = ArticleReviewStatus.SUCCESS.type;
        } else if (passOrNot == YesOrNo.NO.type) {
            //审核失败
            pendingStatus = ArticleReviewStatus.FAILED.type;
        } else {
            //请求参数有问题
            return Result.errorCustom(ResponseStatusEnum.ARTICLE_REVIEW_ERROR);
        }

        articleService.updateArticleStatus(articleId, pendingStatus);

        //todo 生产静态页面
        if (pendingStatus == ArticleReviewStatus.SUCCESS.type) {
            try {
                //createArticleHTML(articleId);
                String articleHTMLToGridFS = createArticleHTMLToGridFS(articleId);
                articleService.updateArticleToGridFS(articleId, articleHTMLToGridFS);
                //调用消费这进行下载html
                //doDownloadArticleHTML(articleId,articleHTMLToGridFS);
                doDownloadArticleHTMLByMQ(articleId, articleHTMLToGridFS);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return Result.ok();
    }


    @Autowired
    private RabbitTemplate rabbitTemplate;


    private void doDownloadArticleHTMLByMQ(String articleId, String articleMongoId) {
        rabbitTemplate.convertAndSend(RabbitMQConfig.EXCHANGER_ARTICLE, "article.test.test", articleId + "," + articleMongoId);
    }


    private void doDownloadArticleHTML(String articleId, String articleMongoId) {
        String url = "http://html.rpnews.com.8002/article/html/download?articleId="
                + articleId
                + "&articleMongoId="
                + articleMongoId;
        ResponseEntity<Integer> forEntity = restTemplate.getForEntity(url, Integer.class);
        Integer status = forEntity.getBody();
        if (status != HttpStatus.SC_OK) {
            GraceException.display(ResponseStatusEnum.ARTICLE_REVIEW_ERROR);
        }
    }


    public String createArticleHTMLToGridFS(String articleId) throws Exception {
        //1.配置freemarker的基本环境
        Configuration cfg = new Configuration(Configuration.getVersion());
        //声明freemarker模板所需要加载的目录位置
        String classpath = this.getClass().getResource("/").getPath();
        cfg.setDirectoryForTemplateLoading(new File(classpath + "templates"));

        log.info("classpath----------------> {}", classpath);
        log.info("classpath+templates----------------> {}", classpath + "templates");

        ArticleDetailVO articleDetail = getArticleDetail(articleId);
        //2.获取现有的模板ftl文件
        Template template = cfg.getTemplate("detail.ftl", "utf-8");

        //3.获取动态数据
        File dicFile = new File(htmlTarget);
        if (!dicFile.exists()) {
            dicFile.mkdirs();
        }

        Map<String, Object> map = new HashMap<>();
        map.put("articleDetail", articleDetail);

        String htmlContent = FreeMarkerTemplateUtils.processTemplateIntoString(template, map);

        log.info("----->{}", htmlContent);
        InputStream inputStream = IOUtils.toInputStream(htmlContent);
        ObjectId objectId = gridFSBucket.uploadFromStream(articleDetail.getId() + ".html", inputStream);
        return objectId.toString();

    }

    public void createArticleHTML(String articleId) throws Exception {
        //1.配置freemarker的基本环境
        Configuration cfg = new Configuration(Configuration.getVersion());
        //声明freemarker模板所需要加载的目录位置
        String classpath = this.getClass().getResource("/").getPath();
        cfg.setDirectoryForTemplateLoading(new File(classpath + "templates"));

        log.info("classpath----------------> {}", classpath);
        log.info("classpath+templates----------------> {}", classpath + "templates");

        ArticleDetailVO articleDetail = getArticleDetail(articleId);
        //2.获取现有的模板ftl文件
        Template template = cfg.getTemplate("detail.ftl", "utf-8");

        //3.获取动态数据
        File dicFile = new File(htmlTarget);
        if (!dicFile.exists()) {
            dicFile.mkdirs();
        }

        Map<String, Object> map = new HashMap<>();
        map.put("articleDetail", articleDetail);

        Writer out = new FileWriter(htmlTarget + File.separator + articleId + ".html");
        template.process(map, out);
        out.close();

    }

    //发起远程请求resttemplate 获取文章详情信息
    private ArticleDetailVO getArticleDetail(String articleId) {
        String url = "http://user.rpnews.com:8003/portal/article/detail?articleId=" + articleId;
        ResponseEntity<Result> forEntity = restTemplate.getForEntity(url, Result.class);
        Result body = forEntity.getBody();
        ArticleDetailVO convert = null;
        if (body.getStatus() == 200) {
            Object data = body.getData();
            convert = Convert.convert(ArticleDetailVO.class, data);
        }
        return convert;
    }

    @PostMapping("/delete")
    @ApiOperation(value = "用户删除文章", notes = "用户删除文章", httpMethod = "POST")
    public Result delete(String articleId, String userId) {
        articleService.deleteArticle(userId, articleId);
        return Result.ok();
    }

    @PostMapping("/withdraw")
    @ApiOperation(value = "用户撤回文章", notes = "用户撤回文章", httpMethod = "POST")
    public Result withdraw(String articleId, String userId) {
        articleService.withdrawArticle(userId, articleId);
        return Result.ok();
    }
}
